﻿using System;
using System.Collections.Generic;

namespace MineSweeperCrip
{
    public class MineSweeperCripCreator
    {
        private string[] mMineField;
        private MineFieldAnalyser mMineFieldAnalyser;

        public MineSweeperCripCreator(string[] strMineField)
        {
            mMineField = strMineField;
            mMineFieldAnalyser = new MineFieldAnalyser();
        }

        public string[] GetMineSweeperCrip()
        {
            if(mMineFieldAnalyser.IsMineFieldCorrect(mMineField))
            {
                List<int> bBoolMineField = CreateBoolArrayFromMineField();
                return CreateMineSweeperCrip(bBoolMineField);
            }

            throw new Exception("MineField is not correct");
        }

        internal string[] CreateMineSweeperCrip(List<int> MineField)
        {
            var EnlargedMineField = EnlargeMineField(MineField);
            var CalculatedMineField =  CalculateBombs(EnlargedMineField.ToArray());

            return TransformtCalculatedMineFieldToStringArray(CalculatedMineField);
        }

        internal string[] TransformtCalculatedMineFieldToStringArray(List<int> CalculatedMineField)
        {
            var TransformedCalculatedMineField = new List<string>();
            string CurrentString = "";
            var NewRowCounter = mMineField[0].Length;

            for (int CurrentCell = 0; CurrentCell < mMineField.Length * mMineField[0].Length; CurrentCell++)
            {
                CurrentString += CalculatedMineField[CurrentCell].ToString();
                NewRowCounter -= 1;

                if(NewRowCounter == 0)
                {
                    TransformedCalculatedMineField.Add(CurrentString);
                    CurrentString = "";
                    NewRowCounter = mMineField[0].Length;
                }
            }

            return TransformedCalculatedMineField.ToArray();
        }

        internal List<int> CalculateBombs(int[] EnlargedMineField)
        {
            //length + 3, lenght + 2, lenght + 1, 1
            var CalculatedMineField = new List<int>();
            int CurrentCellValue;
            var NextLine = false;
            int LineCounter = mMineField[0].Length;

            for (int CellIndex = mMineField[0].Length + 3; CellIndex < EnlargedMineField.Length - (mMineField[0].Length + 3); CellIndex++)
            {
                if(NextLine)
                {
                    NextLine = false;
                    CellIndex += 2;
                }

                CurrentCellValue = 0;
                CurrentCellValue += EnlargedMineField[CellIndex - (mMineField[0].Length + 3)];
                CurrentCellValue += EnlargedMineField[CellIndex - (mMineField[0].Length + 2)];
                CurrentCellValue += EnlargedMineField[CellIndex - (mMineField[0].Length + 1)];
                CurrentCellValue += EnlargedMineField[CellIndex - 1];
                CurrentCellValue += EnlargedMineField[CellIndex + 1];
                CurrentCellValue += EnlargedMineField[CellIndex + (mMineField[0].Length + 1)];
                CurrentCellValue += EnlargedMineField[CellIndex + (mMineField[0].Length + 2)];
                CurrentCellValue += EnlargedMineField[CellIndex + (mMineField[0].Length + 3)];
                CalculatedMineField.Add(CurrentCellValue);

                LineCounter -= 1;

                if(LineCounter == 0)
                {
                    NextLine = true;
                    LineCounter = mMineField[0].Length;
                }
            }

            return CalculatedMineField;
            
        }

        internal List<int> EnlargeMineField(List<int> MineField)
        {
            var EnlargedMineField = new List<int>();

            EnlargedMineField.AddRange(EnlargeMineField_FirstAndLastRow());

            for (int MineFieldRow = 0; MineFieldRow < (MineField.Count / mMineField[0].Length); MineFieldRow ++)
            {
                EnlargedMineField.Add(0);
                EnlargedMineField.AddRange(MineField.GetRange(MineFieldRow * mMineField[0].Length, mMineField[0].Length));
                EnlargedMineField.Add(0);
            }

            EnlargedMineField.AddRange(EnlargeMineField_FirstAndLastRow());

            return EnlargedMineField;
        }

        internal int[] EnlargeMineField_FirstAndLastRow()
        {
            var RowRange = new int[mMineField[0].Length + 2];

            for (int CurrentPositionInMineField = 0; CurrentPositionInMineField < mMineField[0].Length + 2; CurrentPositionInMineField ++)
            {
                RowRange[CurrentPositionInMineField] = 0;
            }

            return RowRange;
        }

        internal List<int> CreateBoolArrayFromMineField()
        {
            var bMineField = new List<int>();
            var bResolvedCurrentMineFieldRow = new List<int>();

            foreach (var strMineFieldRow in mMineField)
            {
                bResolvedCurrentMineFieldRow = ResolveMineFieldRowToBoolArray(strMineFieldRow.ToCharArray());
                bResolvedCurrentMineFieldRow.ForEach(bMineField.Add);
            }

            return bMineField;
        }

        internal List<int> ResolveMineFieldRowToBoolArray(char[] MineFieldRow)
        {
            var bResolvedMineFieldRow = new List<int>();

            foreach (var chrCell in MineFieldRow)
            {
                if(chrCell == ' ')
                {
                    bResolvedMineFieldRow.Add(0);
                }
                else if(chrCell == '*')
                {
                    bResolvedMineFieldRow.Add(1);
                }
                else
                {
                    throw new Exception("Werte im Minenfeld nicht korrekt!");
                }
            }
            return bResolvedMineFieldRow;
        }
    }
}